package utils

import (
	"fmt"
	"sync"
	"time"
)

/*
*

	taskpool效率貌似要高一些
*/
type GoTask struct {
	terminated   byte
	maxworker_n  uint32
	workercnt    uint32
	workerPoolLk *sync.RWMutex
	workerPool   []*GoTaskWoker
}

func NewGoTask(maxworkernum uint32) *GoTask {
	if maxworkernum <= 0 {
		maxworkernum = 4096
	}
	rval := &GoTask{
		maxworker_n:  maxworkernum,
		workerPoolLk: new(sync.RWMutex),
		workerPool:   make([]*GoTaskWoker, 0, int(maxworkernum)),
		terminated:   0,
	}
	return rval
}

func (this *GoTask) Status() string {
	return fmt.Sprintf("worker :%d/%d, terminated:%d", this.workercnt, this.maxworker_n, this.terminated)
}

func (this *GoTask) onWorkerDone(sender *GoTaskWoker) {
	this.workerPoolLk.Lock()
	this.workerPool = append(this.workerPool, sender)
	this.workerPoolLk.Unlock()
}

func (this *GoTask) IsTerminated() bool {
	return this.terminated == 1

}

func (this *GoTask) innerGetWorker() (rval *GoTaskWoker) {
	this.workerPoolLk.Lock()
	defer this.workerPoolLk.Unlock()
	if len(this.workerPool) > 0 {
		rval = this.workerPool[0]
		this.workerPool = append(this.workerPool[:0], this.workerPool[1:]...)
	}

	if rval == nil {
		if this.workercnt < this.maxworker_n {
			rval = NewGoTaskWoker(this, 1024)
			this.workercnt++
		}
	}
	return rval
}

func (this *GoTask) Stop() {
	this.terminated = 1
	this.workerPoolLk.Lock()
	for i := 0; i < len(this.workerPool); i++ {
		this.workerPool[i].Stop()
	}
	this.workerPool = this.workerPool[:0]
	this.workerPoolLk.Unlock()
}

func (this *GoTask) PushTask(fn func(args ...interface{}), args ...interface{}) bool {
	if this.IsTerminated() {
		return false
	}
	wk := this.innerGetWorker()
	if wk == nil {
		return false
	}
	wk.PushTask(fn, args...)
	return true
}

func (this *GoTask) PushTaskEx(fn func(args ...interface{}), args ...interface{}) bool {
	if this.IsTerminated() {
		return false
	}

	var wk *GoTaskWoker
	for {
		wk = this.innerGetWorker()
		if wk != nil {
			break
		}
		time.Sleep(1)
		//runtime.Gosched()
	}
	wk.PushTask(fn, args...)
	return true
}
